package com.ppch.wuwamanus.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ppch.wuwamanus.agent.GameAssistantManus;
import com.ppch.wuwamanus.config.CosClientConfig;
import com.ppch.wuwamanus.config.FileUtils;
import com.ppch.wuwamanus.exception.ErrorCode;
import com.ppch.wuwamanus.exception.ThrowUtils;
import com.ppch.wuwamanus.mapper.ChatHistoryMapper;
import com.ppch.wuwamanus.model.dto.chat_history.ChatHistoryQueryRequest;
import com.ppch.wuwamanus.model.entity.ChatHistory;
import com.ppch.wuwamanus.model.enums.ChatHistoryMessageTypeEnum;
import com.ppch.wuwamanus.service.ChatHistoryService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.List;

/**
 * Package:WuWaManus
 * ClassName:WuWaManusController
 *
 * @Author 泡泡茶壶
 * @Create 2025/9/19 21:21
 * @Version 1.0
 * Description:
 * AI自主规划智能体接口开发
 * 1.SSE流式响应
 * 2.基于MySql的对话记忆持久化（通过实现 ChatMemory 接口实现）
 * 3.支持多轮对话
 */
@RestController
@RequestMapping("/ai/wu_wa_manus")
@Slf4j
public class WuWaManusController {

    @Resource
    private ToolCallback[] allTools;

    @Resource
    private ToolCallbackProvider toolCallbackProvider;

    @Resource
    private ChatModel dashscopeChatModel;

    @Resource
    private FileUtils fileUtils;

    @Resource
    private ChatHistoryService chatHistoryService;

    @Resource
    private ChatHistoryMapper chatHistoryMapper;

    @Resource
    private CosClientConfig cosClientConfig;

    @Resource
    private Advisor dashScopeRetrievalAugmentationAdvisor;


    /**
     * 通过实现ChatMemory接口的方式实现基于MySql的对话记忆持久化和多轮对话
     * TODO：注意由于该接口返回 Flux，处理发生在异步线程。而 RequestContextHolder 基于 ThreadLocal，每个线程拥有自己独立的 ThreadLocal，
     *      所以此时去获取当前登录用户信息是获取不到的，故在该接口使用自定义注解+AOP鉴权会失败，即使登录了也提示未登录。
     * @return Flux<ServerSentEvent<String>> 流式响应
     */
    @GetMapping(value = "/chat")
    public Flux<ServerSentEvent<String>> doChatWithHistory(Long chatId, String userMessage, String messageType, Long userId) {
        //1.校验参数
        ThrowUtils.throwIf(StrUtil.isBlank(userMessage),ErrorCode.PARAMS_ERROR,"用户提示词不能为空");
        ThrowUtils.throwIf(StrUtil.isBlank(messageType),ErrorCode.PARAMS_ERROR,"提示词类型不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(userId),ErrorCode.PARAMS_ERROR,"用户ID不能为空");
        //用于判断是否新增会话，便于前端刷新会话列表
        boolean addNewConversation = false;
        //如果对话 ID 为空，使用雪花算法生成唯一ID
        if(ObjectUtil.isEmpty(chatId)){
            chatId = IdUtil.getSnowflake().nextId();
            addNewConversation = true;
        }
        //2.创建 GameAssistantManus 对象
        GameAssistantManus gameAssistantManus = new GameAssistantManus(allTools, toolCallbackProvider, dashscopeChatModel,
                fileUtils, chatId, userId,20, chatHistoryMapper, cosClientConfig, dashScopeRetrievalAugmentationAdvisor,
                chatHistoryService);
        //3.调用 ManusController.runReactiveStream 方法，返回响应流
        Flux<String> responseStream = gameAssistantManus.runReactiveStream(userMessage);

        Long finalChatId = chatId;
        boolean finalAddNewConversation = addNewConversation;

        //4.处理响应数据
        Flux<ServerSentEvent<String>> mainFlux = responseStream
                .map(chunk -> {
                    // 处理自定义事件：PDF文件事件
                    if (chunk.contains("SEND_PDF_FILE")) {
                        String pdfUrl = chunk.replace("SEND_PDF_FILE", "");
                        // 检查数据库是否已存在该记录，避免重复
                        LambdaQueryWrapper<ChatHistory> queryWrapper = chatHistoryService.getQueryWrapper(
                                new ChatHistoryQueryRequest(null, pdfUrl, ChatHistoryMessageTypeEnum.SEND_PDF_FILE.getValue(),
                                        finalChatId, userId, null));
                        List<ChatHistory> list = chatHistoryService.list(queryWrapper);
                        if (list.size() > 0) {
                            return ServerSentEvent.<String>builder()
                                    .data("已生成相同的PDF文件，可查看历史记录。")
                                    .build();
                        } else {
                            // 保存PDF事件到数据库
                            chatHistoryService.addChatHistory(finalChatId, pdfUrl,
                                    ChatHistoryMessageTypeEnum.SEND_PDF_FILE.getValue(), userId);
                            return ServerSentEvent.<String>builder()
                                    .event(ChatHistoryMessageTypeEnum.SEND_PDF_FILE.getValue())
                                    .data(pdfUrl)
                                    .build();
                        }
                    }
                    // 处理自定义事件：抽卡分析事件
                    else if (chunk.contains("SEND_CARD_DRAWING_ANALYSIS")) {
                        String analysisData = chunk.replace("SEND_CARD_DRAWING_ANALYSIS", "");
                        LambdaQueryWrapper<ChatHistory> queryWrapper = chatHistoryService.getQueryWrapper(
                                new ChatHistoryQueryRequest(null, analysisData, ChatHistoryMessageTypeEnum.SEND_CARD_DRAWING_ANALYSIS.getValue(),
                                        finalChatId, userId, null));
                        List<ChatHistory> list = chatHistoryService.list(queryWrapper);
                        if (list.size() > 0) {
                            return ServerSentEvent.<String>builder()
                                    .data("无需重复查询，可查看历史记录。")
                                    .build();
                        } else {
                            chatHistoryService.addChatHistory(finalChatId, analysisData,
                                    ChatHistoryMessageTypeEnum.SEND_CARD_DRAWING_ANALYSIS.getValue(), userId);
                            return ServerSentEvent.<String>builder()
                                    .event(ChatHistoryMessageTypeEnum.SEND_CARD_DRAWING_ANALYSIS.getValue())
                                    .data(analysisData)
                                    .build();
                        }
                    }
                    // 普通消息事件
                    else {
                        return ServerSentEvent.<String>builder()
                                .data(chunk)
                                .build();
                    }
                })
                .doOnComplete(() -> {})
                .doOnError(error -> {
                    // 错误处理
                    log.error("AI响应流处理失败, chatId: {}", finalChatId, error);
                })
                .onErrorResume(e -> {
                    String errorMessage = "AI 回复失败：" + e.getMessage();
                    return Flux.just(ServerSentEvent.<String>builder()
                            .data(errorMessage)
                            .build());
                });
        // finalAddNewConversation 为 true 时才发送新增会话事件
        if (finalAddNewConversation) {
            ServerSentEvent<String> newConversationEvent = ServerSentEvent.<String>builder()
                    .event(ChatHistoryMessageTypeEnum.SEND_ADD_NEW_CONVERSATION.getValue())
                    .data(finalChatId.toString())
                    .build();
            return mainFlux.concatWithValues(newConversationEvent);
        } else {
            return mainFlux;
        }
    }

}
